#include <REGX52.H>

//用于定义，将地址分别重新定义，便于使用和管理
#define DS1302_SECOND     0x80
#define DS1302_MINUTE     0x82
#define DS1302_HOUR       0x84
#define DS1302_DATE       0x86
#define DS1302_MONTH      0x88
#define DS1302_DAY        0x8A
#define DS1302_YEAR       0x8C
#define DS1302_WP         0x8E



//定义端口（引脚）方便后期改端口参数
sbit DS1302_SCLK=P3^6;
sbit DS1302_IO=P3^4;
sbit DS1302_CE=P3^5;


//时间数组，索引0~6分别为年、月、日、时、分、秒、星期
unsigned char DS1302_Time[]={24,8,20,21,32,2};


/**
  * @brief  DS1302初始化
  * @param  无
  * @retval 无
  */
void DS1302_Init(void)  //单片机的初始化
{
	DS1302_CE=0;
	DS1302_SCLK=0;
}



/**
  * @brief  DS1302写入一个字节
  * @param  Command 命令字/地址
			Data 要写入的数据
  * @retval 无
  */
void DS1302_WriteByte(unsigned char Command,Data)
{
	unsigned char i;
	DS1302_CE=1;  //时序置1
	for(i=0;i<8;i++)  //写入地址命令字
	{
		DS1302_IO=Command&(0x01<<i); //一位一位的提取命令字的数据，注意从低位开始取
		DS1302_SCLK=1;
		DS1302_SCLK=0; //应该考虑时钟的最快频率，这里51单片机速率较慢，可以不加延时
	}
	
	for(i=0;i<8;i++)  //写入输入的数据，具体逻辑和上面的for循环逻辑一致
	{
		DS1302_IO=Data&(0x01<<i); 
		DS1302_SCLK=1;
		DS1302_SCLK=0;
	}
	DS1302_CE=0; //时序置零
}



/**
  * @brief  DS1302读一字节
  * @param  Command 命令字/地址
  * @retval 读出的数据
  */
unsigned char DS1302_ReadByte(unsigned char Command)
{
	unsigned char i,Data=0x00; //局部变量初始化不一定默认是0，需要进行初始化
	DS1302_CE=1;  //时序置1
	for(i=0;i<8;i++)  //读取地址命令字
	{
		DS1302_IO=Command&(0x01<<i); //提取命令字的数据，注意从低位开始取
		DS1302_SCLK=0;
		DS1302_SCLK=1;  
//由于读取数据时有15个脉冲（比写入少一个）
//则需要在写入最后一个时钟地址命令字时，阻止时钟第一个数据的读出，则需要调换01顺序，保证在第一个数据读取之前脉冲仍在上升沿
	}
	
	for(i=0;i<8;i++)  //时钟读取输入的数据用于显示
	{
		DS1302_SCLK=1;   //与上一个循环结尾点位相同则总电平没有变化，意义是去掉一个脉冲保证有15个脉冲
		DS1302_SCLK=0;  //需要保证在循环8位后脉冲为0
		if(DS1302_IO){Data|=(0x01<<i);}
//if用于检测IO口的控制是否转交给时钟芯片，若已转交就开始读出数据
	}
	DS1302_CE=0;
	DS1302_IO=0;
	return Data;
}	



/**
  * @brief  DS1302设置时间，调用之后，DS1302_Time数组的数字会被设置到DS1302中
  * @param  无
  * @retval 无
  */
void DS1302_SetTime(void)  //用于设置（导入）数据，不需要一条条的编写年月日，直接声明函数就可以进入编写程序
{
	DS1302_WriteByte(DS1302_WP,0x00);  //关闭写入保护防止数据无法输入进时钟芯片
	DS1302_WriteByte(DS1302_YEAR,DS1302_Time[0]/10*16+DS1302_Time[0]%10);
//地址数据需要通过BCD码存储，利用公式将十进制转化成BCD码写入
	DS1302_WriteByte(DS1302_MONTH,DS1302_Time[1]/10*16+DS1302_Time[1]%10);
	DS1302_WriteByte(DS1302_DATE,DS1302_Time[2]/10*16+DS1302_Time[2]%10);
	DS1302_WriteByte(DS1302_HOUR,DS1302_Time[3]/10*16+DS1302_Time[3]%10);
	DS1302_WriteByte(DS1302_MINUTE,DS1302_Time[4]/10*16+DS1302_Time[4]%10);
	DS1302_WriteByte(DS1302_SECOND,DS1302_Time[5]/10*16+DS1302_Time[5]%10);
	DS1302_WriteByte(DS1302_DAY,DS1302_Time[6]/10*16+DS1302_Time[6]%10);
	DS1302_WriteByte(DS1302_WP,0x00);  //打开写入保护
}




/**
  * @brief  DS1302读取时间，调用之后，DS1302中的数据会被读取到DS1302_Time数组中
  * @param  无
  * @retval 无
  */
void DS1302_ReadTime(void)  //用于读取数据
{
	unsigned char Temp;
	Temp=DS1302_ReadByte(DS1302_YEAR+1);
	DS1302_Time[0]=Temp/16*10+Temp%16;
	Temp=DS1302_ReadByte(DS1302_MONTH+1);
	DS1302_Time[1]=Temp/16*10+Temp%16;
	Temp=DS1302_ReadByte(DS1302_DATE+1);
	DS1302_Time[2]=Temp/16*10+Temp%16;
	Temp=DS1302_ReadByte(DS1302_HOUR+1);
	DS1302_Time[3]=Temp/16*10+Temp%16;
	Temp=DS1302_ReadByte(DS1302_MINUTE+1);
	DS1302_Time[4]=Temp/16*10+Temp%16;
	Temp=DS1302_ReadByte(DS1302_SECOND+1);
	DS1302_Time[5]=Temp/16*10+Temp%16;
	Temp=DS1302_ReadByte(DS1302_DAY+1);
	DS1302_Time[6]=Temp/16*10+Temp%16;
//Read函数与write的寻址应该一样，应把里面的参数都加一
}